<!DOCTYPE html>

<html>
<head>
  <title>peers.js</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  <link rel="stylesheet" media="all" href="arkio.css" />
</head>
<body>
  
    <div id="title">
         <h1>peers.js</h1>
         <img src="https://ark.io/wp-content/uploads/2016/10/ark-normal.png">
        <hr>
    </div>
  
  <div id="container">
    <div id="background"></div>
    
      <ul id="jump_to">
        <li>
          <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
          <a class="small" href="javascript:void(0);">+</a>
          <div id="jump_wrapper">
          <div id="jump_page_wrapper">
            <div id="jump_page">
              
                
                <a class="source" href="README.html">
                  README.md
                </a>
              
                
                <a class="source" href="app.html">
                  app.js
                </a>
              
                
                <a class="source" href="accounts.html">
                  accounts.js
                </a>
              
                
                <a class="source" href="blockchain.html">
                  blockchain.js
                </a>
              
                
                <a class="source" href="blocks.html">
                  blocks.js
                </a>
              
                
                <a class="source" href="delegates.html">
                  delegates.js
                </a>
              
                
                <a class="source" href="loader.html">
                  loader.js
                </a>
              
                
                <a class="source" href="multisignatures.html">
                  multisignatures.js
                </a>
              
                
                <a class="source" href="nodeManager.html">
                  nodeManager.js
                </a>
              
                
                <a class="source" href="peers.html">
                  peers.js
                </a>
              
                
                <a class="source" href="rounds.html">
                  rounds.js
                </a>
              
                
                <a class="source" href="server.html">
                  server.js
                </a>
              
                
                <a class="source" href="signatures.html">
                  signatures.js
                </a>
              
                
                <a class="source" href="system.html">
                  system.js
                </a>
              
                
                <a class="source" href="transactionPool.html">
                  transactionPool.js
                </a>
              
                
                <a class="source" href="transactions.html">
                  transactions.js
                </a>
              
                
                <a class="source" href="transport.html">
                  transport.js
                </a>
              
            </div>
          </div>
        </li>
      </ul>
    
    <ul class="sections">
        
        
        <li id="section-1">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-1">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-meta">'use strict'</span>;

<span class="hljs-keyword">var</span> _ = <span class="hljs-built_in">require</span>(<span class="hljs-string">'lodash'</span>);
<span class="hljs-keyword">var</span> <span class="hljs-keyword">async</span> = <span class="hljs-built_in">require</span>(<span class="hljs-string">'async'</span>);
<span class="hljs-keyword">var</span> extend = <span class="hljs-built_in">require</span>(<span class="hljs-string">'extend'</span>);
<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
<span class="hljs-keyword">var</span> ip = <span class="hljs-built_in">require</span>(<span class="hljs-string">'ip'</span>);
<span class="hljs-keyword">var</span> OrderBy = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../helpers/orderBy.js'</span>);
<span class="hljs-keyword">var</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>);
<span class="hljs-keyword">var</span> Router = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../helpers/router.js'</span>);
<span class="hljs-keyword">var</span> schema = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../schema/peers.js'</span>);
<span class="hljs-keyword">var</span> sql = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../sql/peers.js'</span>);
<span class="hljs-keyword">var</span> util = <span class="hljs-built_in">require</span>(<span class="hljs-string">'util'</span>);</pre></div></div>
            
        </li>
        
        
        <li id="section-2">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-2">&#182;</a>
              </div>
              <p>Private fields</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> modules, library, self, __private = {}, shared = {};</pre></div></div>
            
        </li>
        
        
        <li id="section-3">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-3">&#182;</a>
              </div>
              <p>List of peers not behaving well
reset when we restart</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> removed = [];</pre></div></div>
            
        </li>
        
        
        <li id="section-4">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-4">&#182;</a>
              </div>
              <p>Constructor</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Peers</span> (<span class="hljs-params">cb, scope</span>) </span>{
	library = scope;
	self = <span class="hljs-keyword">this</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-5">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-5">&#182;</a>
              </div>
              <p>prevents from looking too much around at coldstart</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>	__private.lastPeersUpdate = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();</pre></div></div>
            
        </li>
        
        
        <li id="section-6">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-6">&#182;</a>
              </div>
              <p>not banning at the start of nodes</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>	__private.coldstart = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();</pre></div></div>
            
        </li>
        
        
        <li id="section-7">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-7">&#182;</a>
              </div>
              <p>hold the peer list</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>	__private.peers = {};</pre></div></div>
            
        </li>
        
        
        <li id="section-8">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-8">&#182;</a>
              </div>
              <p>peers that have timeout, so there are not used for time sensitive acctions</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>	__private.timeoutPeers = {};

	setImmediate(cb, <span class="hljs-literal">null</span>, self);
}</pre></div></div>
            
        </li>
        
        
        <li id="section-9">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-9">&#182;</a>
              </div>
              <p>Private methods</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>__private.attachApi = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
	<span class="hljs-keyword">var</span> router = <span class="hljs-keyword">new</span> Router();

	router.use(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req, res, next</span>) </span>{
		<span class="hljs-keyword">if</span> (modules) { <span class="hljs-keyword">return</span> next(); }
		res.status(<span class="hljs-number">500</span>).send({<span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>, <span class="hljs-attr">error</span>: <span class="hljs-string">'Blockchain is loading'</span>});
	});

	router.map(shared, {
		<span class="hljs-string">'get /'</span>: <span class="hljs-string">'getPeers'</span>,
		<span class="hljs-string">'get /version'</span>: <span class="hljs-string">'version'</span>,
		<span class="hljs-string">'get /get'</span>: <span class="hljs-string">'getPeer'</span>
	});

	router.use(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req, res</span>) </span>{
		res.status(<span class="hljs-number">500</span>).send({<span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>, <span class="hljs-attr">error</span>: <span class="hljs-string">'API endpoint not found'</span>});
	});

	library.network.app.use(<span class="hljs-string">'/api/peers'</span>, router);
	library.network.app.use(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, req, res, next</span>) </span>{
		<span class="hljs-keyword">if</span> (!err) { <span class="hljs-keyword">return</span> next(); }
		library.logger.error(<span class="hljs-string">'API error '</span> + req.url, err);
		res.status(<span class="hljs-number">500</span>).send({<span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>, <span class="hljs-attr">error</span>: <span class="hljs-string">'API error: '</span> + err.message});
	});
};

__private.updatePeersList = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">cb</span>) </span>{
	library.logger.debug(<span class="hljs-string">'updating Peers List...'</span>);
	__private.lastPeersUpdate = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
	modules.transport.getFromRandomPeer({
		<span class="hljs-attr">api</span>: <span class="hljs-string">'/list'</span>,
		<span class="hljs-attr">method</span>: <span class="hljs-string">'GET'</span>
	}, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, res</span>) </span>{
		<span class="hljs-keyword">if</span> (err) {
			library.logger.debug(<span class="hljs-string">'peers validation error '</span>, err);
			<span class="hljs-keyword">return</span> setImmediate(cb);
		}

		library.schema.validate(res.body, schema.updatePeersList.peers, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
			<span class="hljs-keyword">if</span> (err) {
				library.logger.debug(<span class="hljs-string">'peers validation error '</span>, err);
				<span class="hljs-keyword">return</span> setImmediate(cb);
			}</pre></div></div>
            
        </li>
        
        
        <li id="section-10">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-10">&#182;</a>
              </div>
              <p>Removing nodes not behaving well</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>			library.logger.debug(<span class="hljs-string">'Removed peers: '</span> + removed.length);
			<span class="hljs-keyword">var</span> peers = res.body.peers.filter(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">peer</span>) </span>{
					<span class="hljs-keyword">return</span> removed.indexOf(peer.ip+<span class="hljs-string">":"</span>+peer.port);
			});</pre></div></div>
            
        </li>
        
        
        <li id="section-11">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-11">&#182;</a>
              </div>
              <p>Update only a subset of the peers to decrease the noise on the network.
Default is 20 peers. To be fined tuned. Node gets checked by a peer every 3s on average.
Maybe increasing schedule (every 60s right now).</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>			<span class="hljs-keyword">var</span> maxUpdatePeers = <span class="hljs-built_in">Math</span>.floor(library.config.peers.options.maxUpdatePeers) || <span class="hljs-number">50</span>;
			<span class="hljs-keyword">if</span> (peers.length &gt; maxUpdatePeers) {
				peers = peers.slice(<span class="hljs-number">0</span>, maxUpdatePeers);
			}</pre></div></div>
            
        </li>
        
        
        <li id="section-12">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-12">&#182;</a>
              </div>
              <p>Drop one random peer from removed array to give them a chance.
This mitigates the issue that a node could be removed forever if it was offline for long.
This is not harmful for the node, but prevents network from shrinking, increasing noise.
To fine tune: decreasing random value threshold -&gt; reduce noise.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>			<span class="hljs-keyword">if</span> (<span class="hljs-built_in">Math</span>.random() &lt; <span class="hljs-number">0.5</span>) { <span class="hljs-comment">// Every 60/0.5 = 120s</span></pre></div></div>
            
        </li>
        
        
        <li id="section-13">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-13">&#182;</a>
              </div>
              <p>Remove the first element,
i.e. the one that have been placed first.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>				removed.shift();
				removed.pop();
			}

			library.logger.debug([<span class="hljs-string">'Picked'</span>, peers.length, <span class="hljs-string">'of'</span>, res.body.peers.length, <span class="hljs-string">'peers'</span>].join(<span class="hljs-string">' '</span>));

			<span class="hljs-keyword">async</span>.eachLimit(peers, <span class="hljs-number">2</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">peer, cb</span>) </span>{
				peer = self.inspect(peer);

				library.schema.validate(peer, schema.updatePeersList.peer, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
					<span class="hljs-keyword">if</span> (err) {
						err.forEach(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
							library.logger.error([<span class="hljs-string">'Rejecting invalid peer:'</span>, peer.ip, e.path, e.message].join(<span class="hljs-string">' '</span>));
						});

						<span class="hljs-keyword">return</span> setImmediate(cb);
					} <span class="hljs-keyword">else</span> {
						__private.peers[peer.ip+<span class="hljs-string">":"</span>+peer.port] = peer;
						<span class="hljs-keyword">return</span> setImmediate(cb);
					}
				});
			}, cb);
		});
	});
};

__private.count = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">cb</span>) </span>{
	<span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-literal">null</span>, <span class="hljs-built_in">Object</span>.keys(__private.peers).length);
};

__private.banManager = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">cb</span>) </span>{
	<span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-literal">null</span>, <span class="hljs-number">1</span>);</pre></div></div>
            
        </li>
        
        
        <li id="section-14">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-14">&#182;</a>
              </div>
              <p>library.db.query(sql.banManager, { now: Date.now() }).then(function (res) {
    return setImmediate(cb, null, res);
}).catch(function (err) {
    library.logger.error(“stack”, err.stack);
    return setImmediate(cb, ‘Peers#banManager error’);
});</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>};

__private.getByFilter = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">filter, cb</span>) </span>{
	<span class="hljs-keyword">var</span> where = [];
	<span class="hljs-keyword">var</span> params = {};

	<span class="hljs-keyword">if</span> (filter.state) {
		where.push(<span class="hljs-string">'"state" = ${state}'</span>);
		params.state = filter.state;
	}

	<span class="hljs-keyword">if</span> (filter.os) {
		where.push(<span class="hljs-string">'"os" = ${os}'</span>);
		params.os = filter.os;
	}

	<span class="hljs-keyword">if</span> (filter.version) {
		where.push(<span class="hljs-string">'"version" = ${version}'</span>);
		params.version = filter.version;
	}

	<span class="hljs-keyword">if</span> (filter.ip) {
		where.push(<span class="hljs-string">'"ip" = ${ip}'</span>);
		params.ip = filter.ip;
	}

	<span class="hljs-keyword">if</span> (filter.port) {
		where.push(<span class="hljs-string">'"port" = ${port}'</span>);
		params.port = filter.port;
	}

	<span class="hljs-keyword">if</span> (!filter.limit) {
		params.limit = <span class="hljs-number">100</span>;
	} <span class="hljs-keyword">else</span> {
		params.limit = <span class="hljs-built_in">Math</span>.abs(filter.limit);
	}

	<span class="hljs-keyword">if</span> (!filter.offset) {
		params.offset = <span class="hljs-number">0</span>;
	} <span class="hljs-keyword">else</span> {
		params.offset = <span class="hljs-built_in">Math</span>.abs(filter.offset);
	}

	<span class="hljs-keyword">if</span> (params.limit &gt; <span class="hljs-number">100</span>) {
		<span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-string">'Invalid limit. Maximum is 100'</span>);
	}

	<span class="hljs-keyword">var</span> orderBy = OrderBy(
		filter.orderBy, {
			<span class="hljs-attr">sortFields</span>: sql.sortFields
		}
	);

	<span class="hljs-keyword">if</span> (orderBy.error) {
		<span class="hljs-keyword">return</span> setImmediate(cb, orderBy.error);
	}

	<span class="hljs-keyword">return</span> self.list({},cb);</pre></div></div>
            
        </li>
        
        
        <li id="section-15">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-15">&#182;</a>
              </div>
              <p>library.db.query(sql.getByFilter({
    where: where,
    sortField: orderBy.sortField,
    sortMethod: orderBy.sortMethod
}), params).then(function (rows) {
    return setImmediate(cb, null, rows);
}).catch(function (err) {
    library.logger.error(“stack”, err.stack);
    return setImmediate(cb, ‘Peers#getByFilter error’);
});</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>};</pre></div></div>
            
        </li>
        
        
        <li id="section-16">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-16">&#182;</a>
              </div>
              <p>Public methods</p>
<p><strong>API</strong> <code>inspect</code></p>

            </div>
            
        </li>
        
        
        <li id="section-17">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-17">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.inspect = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">peer</span>) </span>{
	<span class="hljs-keyword">if</span>(peer == <span class="hljs-number">-1</span>){
		<span class="hljs-keyword">return</span> {};
	}
	<span class="hljs-keyword">if</span> (<span class="hljs-regexp">/^[0-9]+$/</span>.test(peer.ip)) {
		peer.ip = ip.fromLong(peer.ip);
	}
	<span class="hljs-keyword">if</span>(peer.port){
		peer.port = <span class="hljs-built_in">parseInt</span>(peer.port);
	}

	<span class="hljs-keyword">if</span> (peer.ip) {
		peer.string = (peer.ip + <span class="hljs-string">':'</span> + peer.port || <span class="hljs-string">'unknown'</span>);
	} <span class="hljs-keyword">else</span> {
		peer.string = <span class="hljs-string">'unknown'</span>;
	}

	peer.os = peer.os || <span class="hljs-string">'unknown'</span>;
	peer.version = peer.version || <span class="hljs-string">'0.0.0'</span>;

	<span class="hljs-keyword">return</span> peer;
};</pre></div></div>
            
        </li>
        
        
        <li id="section-18">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-18">&#182;</a>
              </div>
              <p>send peers, with in priority peers that seems to be in same chain</p>
<p><strong>API</strong> <code>list</code></p>

            </div>
            
        </li>
        
        
        <li id="section-19">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-19">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.list = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">options, cb</span>) </span>{

	<span class="hljs-keyword">var</span> peers=<span class="hljs-built_in">Object</span>.keys(__private.peers);

	<span class="hljs-keyword">var</span> list = peers.map(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">key</span>) </span>{
    <span class="hljs-keyword">return</span> __private.peers[key];
	});

	<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">shuffle</span>(<span class="hljs-params">array</span>) </span>{
	  <span class="hljs-keyword">var</span> currentIndex = array.length, temporaryValue, randomIndex;</pre></div></div>
            
        </li>
        
        
        <li id="section-20">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-20">&#182;</a>
              </div>
              <p>While there remain elements to shuffle…</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>	  <span class="hljs-keyword">while</span> (<span class="hljs-number">0</span> !== currentIndex) {</pre></div></div>
            
        </li>
        
        
        <li id="section-21">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-21">&#182;</a>
              </div>
              <p>Pick a remaining element…</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>	    randomIndex = <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * currentIndex);
	    currentIndex -= <span class="hljs-number">1</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-22">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-22">&#182;</a>
              </div>
              <p>And swap it with the current element.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>	    temporaryValue = array[currentIndex];
	    array[currentIndex] = array[randomIndex];
	    array[randomIndex] = temporaryValue;
	  }

	  <span class="hljs-keyword">return</span> array;
	}

	list = shuffle(list).sort(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">a, b</span>)</span>{
		<span class="hljs-keyword">if</span>(a.blockheader){
			<span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
		}
		<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(b.blockheader){
			<span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
		}
		<span class="hljs-keyword">else</span> {
			<span class="hljs-keyword">return</span> <span class="hljs-number">10000</span>;
		}
	});

	<span class="hljs-keyword">return</span> cb(<span class="hljs-literal">null</span>, list);</pre></div></div>
            
        </li>
        
        
        <li id="section-23">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-23">&#182;</a>
              </div>
              <p>options.limit = options.limit || 100;</p>
<p>library.db.query(sql.randomList(options), options).then(function (rows) {
    return setImmediate(cb, null, rows);
}).catch(function (err) {
    library.logger.error(“stack”, err.stack);
    return setImmediate(cb, ‘Peers#list error’);
});</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>};</pre></div></div>
            
        </li>
        
        
        <li id="section-24">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-24">&#182;</a>
              </div>
              <p><strong>API</strong> <code>state</code></p>

            </div>
            
        </li>
        
        
        <li id="section-25">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-25">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.state = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">pip, port, state, timeoutSeconds, cb</span>) </span>{
	<span class="hljs-keyword">var</span> isFrozenList = _.find(library.config.peers, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">peer</span>) </span>{
		<span class="hljs-keyword">return</span> peer.ip === pip &amp;&amp; peer.port === port;
	});
	<span class="hljs-keyword">if</span> (isFrozenList !== <span class="hljs-literal">undefined</span> &amp;&amp; cb) {
		<span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-string">'Peer in white list'</span>);
	}
	<span class="hljs-keyword">var</span> clock;
	<span class="hljs-keyword">if</span> (state === <span class="hljs-number">0</span>) {
		clock = (timeoutSeconds || <span class="hljs-number">1</span>) * <span class="hljs-number">1000</span>;
		clock = <span class="hljs-built_in">Date</span>.now() + clock;
	} <span class="hljs-keyword">else</span> {
		clock = <span class="hljs-literal">null</span>;
	}
	<span class="hljs-keyword">var</span> params = {
		<span class="hljs-attr">state</span>: state,
		<span class="hljs-attr">clock</span>: clock,
		<span class="hljs-attr">ip</span>: pip,
		<span class="hljs-attr">port</span>: port
	};
	library.db.query(sql.state, params).then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">res</span>) </span>{
		library.logger.debug(<span class="hljs-string">'Updated peer state'</span>, params);
		<span class="hljs-keyword">return</span> cb &amp;&amp; setImmediate(cb, <span class="hljs-literal">null</span>, res);
	}).catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
		library.logger.error(<span class="hljs-string">"stack"</span>, err.stack);
		<span class="hljs-keyword">return</span> cb &amp;&amp; setImmediate(cb);
	});
};</pre></div></div>
            
        </li>
        
        
        <li id="section-26">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-26">&#182;</a>
              </div>
              <p><strong>API</strong> <code>timeoutPeer</code></p>

            </div>
            
        </li>
        
        
        <li id="section-27">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-27">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.timeoutPeer = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">peer</span>)</span>{
	<span class="hljs-keyword">if</span>(__private.coldstart+<span class="hljs-number">10000</span> &lt; <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime()){
		__private.timeoutPeers[peer.ip+<span class="hljs-string">":"</span>+peer.port] = peer;
		self.remove(peer.ip, peer.port);
	}
}</pre></div></div>
            
        </li>
        
        
        <li id="section-28">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-28">&#182;</a>
              </div>
              <p><strong>API</strong> <code>releaseTimeoutPeers</code></p>

            </div>
            
        </li>
        
        
        <li id="section-29">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-29">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.releaseTimeoutPeers = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{
	<span class="hljs-keyword">async</span>.each(<span class="hljs-built_in">Object</span>.keys(__private.timeoutPeers), <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">peerstring, cb</span>) </span>{
		<span class="hljs-keyword">var</span> peer = __private.timeoutPeers[peerstring];
		modules.transport.getFromPeer(peer, {
			<span class="hljs-attr">api</span>: <span class="hljs-string">'/height'</span>,
			<span class="hljs-attr">method</span>: <span class="hljs-string">'GET'</span>,
			<span class="hljs-attr">timeout</span>: <span class="hljs-number">2000</span>
		}, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>)</span>{
			<span class="hljs-keyword">if</span>(!error){
				<span class="hljs-keyword">delete</span> __private.timeoutPeers[peerstring];
				self.update(peer);
			}
			<span class="hljs-keyword">return</span> cb();
		});
	});
}</pre></div></div>
            
        </li>
        
        
        <li id="section-30">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-30">&#182;</a>
              </div>
              <p><strong>API</strong> <code>remove</code></p>

            </div>
            
        </li>
        
        
        <li id="section-31">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-31">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.remove = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">pip, port</span>) </span>{
	<span class="hljs-keyword">var</span> isFrozenList = library.config.peers.list.find(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">peer</span>) </span>{
		<span class="hljs-keyword">return</span> peer.ip === pip &amp;&amp; peer.port === port;
	});
	<span class="hljs-keyword">if</span> (isFrozenList) {
		<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
	}</pre></div></div>
            
        </li>
        
        
        <li id="section-32">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-32">&#182;</a>
              </div>
              <p>to prevent from reappearing too often it is added to “removed”</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>	<span class="hljs-keyword">if</span>(removed.indexOf(pip+<span class="hljs-string">":"</span>+port) == <span class="hljs-number">-1</span>){
		removed.push(pip+<span class="hljs-string">":"</span>+port);
	}
	<span class="hljs-keyword">delete</span> __private.peers[pip+<span class="hljs-string">":"</span>+port];
	<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-33">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-33">&#182;</a>
              </div>
              <p>library.db.query(sql.remove, params).then(function (res) {
    library.logger.debug(‘Removed peer’, params);
    return cb &amp;&amp; setImmediate(cb, null, res);
}).catch(function (err) {
    library.logger.error(“stack”, err.stack);
    return cb &amp;&amp; setImmediate(cb);
});</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>};</pre></div></div>
            
        </li>
        
        
        <li id="section-34">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-34">&#182;</a>
              </div>
              <p><strong>API</strong> <code>update</code></p>

            </div>
            
        </li>
        
        
        <li id="section-35">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-35">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.update = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">peer</span>) </span>{</pre></div></div>
            
        </li>
        
        
        <li id="section-36">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-36">&#182;</a>
              </div>
              <p>var params = {
    ip: peer.ip,
    port: peer.port,
    os: peer.os || null,
    version: peer.version || null,
    state: 1
};</p>

            </div>
            
        </li>
        
        
        <li id="section-37">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-37">&#182;</a>
              </div>
              <p>var query;
if (peer.state !== undefined) {
    params.state = peer.state;
    query = sql.upsertWithState;
} else {
    query = sql.upsertWithoutState;
}</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>	<span class="hljs-keyword">if</span>(removed.indexOf(peer.ip+<span class="hljs-string">":"</span>+peer.port) &gt; <span class="hljs-number">-1</span>){
		<span class="hljs-keyword">return</span>;
	}
	<span class="hljs-keyword">if</span>(__private.peers[(peer.ip+<span class="hljs-string">":"</span>+peer.port)]){
		<span class="hljs-keyword">if</span>(peer.blockheader){
			<span class="hljs-keyword">var</span> lastBlock = modules.blockchain.getLastBlock()
			<span class="hljs-keyword">if</span>(peer.blockheader.height &gt; lastBlock.height &amp;&amp; peer.blockheader.timestamp &gt; lastBlock.timestamp){
				__private.peers[(peer.ip+<span class="hljs-string">":"</span>+peer.port)] = peer;
				__private.peers[(peer.ip+<span class="hljs-string">":"</span>+peer.port)].height = peer.blockheader.height;
			}
			<span class="hljs-keyword">else</span>{
				self.remove(peer.ip,peer.port);
			}
		}
		<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(peer.height){
			__private.peers[(peer.ip+<span class="hljs-string">":"</span>+peer.port)].height = peer.height
		}
	}
	<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(peer.port &amp;&amp; <span class="hljs-built_in">parseInt</span>(peer.port)!=<span class="hljs-number">1</span> &amp;&amp; !__private.timeoutPeers[peer.ip+<span class="hljs-string">":"</span>+peer.port]){
		__private.peers[(peer.ip+<span class="hljs-string">":"</span>+peer.port)] = peer;
		library.logger.debug(<span class="hljs-string">"New peer added"</span>, peer);
	}</pre></div></div>
            
        </li>
        
        
        <li id="section-38">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-38">&#182;</a>
              </div>
              <p>library.db.query(query, params).then(function () {
    library.logger.debug(‘Upserted peer’, params);
    return setImmediate(cb);
}).catch(function (err) {
    library.logger.error(“stack”, err.stack);
    return setImmediate(cb, ‘Peers#update error’);
});</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>};</pre></div></div>
            
        </li>
        
        
        <li id="section-39">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-39">&#182;</a>
              </div>
              <p><strong>API</strong> <code>getFreshPeer</code></p>

            </div>
            
        </li>
        
        
        <li id="section-40">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-40">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.getFreshPeer = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">peer</span>) </span>{
	<span class="hljs-keyword">return</span> __private.peers[peer.ip+<span class="hljs-string">":"</span>+peer.port];
}</pre></div></div>
            
        </li>
        
        
        <li id="section-41">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-41">&#182;</a>
              </div>
              <p>Events</p>
<p><strong>EVENT</strong> <code>onBind</code></p>

            </div>
            
        </li>
        
        
        <li id="section-42">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-42">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.onBind = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">scope</span>) </span>{
	modules = scope;
	<span class="hljs-keyword">for</span>(<span class="hljs-keyword">var</span> i=<span class="hljs-number">0</span>;i&lt;library.config.peers.list.length;i++){
		<span class="hljs-keyword">var</span> peer = library.config.peers.list[i];
		__private.peers[peer.ip+<span class="hljs-string">":"</span>+peer.port] = peer;
	}
};</pre></div></div>
            
        </li>
        
        
        <li id="section-43">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-43">&#182;</a>
              </div>
              <p><strong>EVENT</strong> <code>onAttachPublicApi</code></p>

            </div>
            
        </li>
        
        
        <li id="section-44">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-44">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.onAttachPublicApi = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
 	__private.attachApi();
};</pre></div></div>
            
        </li>
        
        
        <li id="section-45">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-45">&#182;</a>
              </div>
              <p><strong>EVENT</strong> <code>onUpdatePeers</code></p>

            </div>
            
        </li>
        
        
        <li id="section-46">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-46">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.onUpdatePeers = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
	__private.updatePeersList(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
		<span class="hljs-keyword">if</span> (err) {
			library.logger.error(<span class="hljs-string">'Error while updating the list of peers:'</span>, err);
		}
		library.bus.message(<span class="hljs-string">'peersUpdated'</span>);
	});

	setImmediate(<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nextUpdate</span> (<span class="hljs-params"></span>) </span>{
		__private.updatePeersList(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
			<span class="hljs-keyword">if</span> (err) {
				library.logger.error(<span class="hljs-string">'Error while updating the list of peers:'</span>, err);
			}
			setTimeout(nextUpdate, <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>);
		});
	});
};</pre></div></div>
            
        </li>
        
        
        <li id="section-47">
          
            <div class="fullblock">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-47">&#182;</a>
              </div>
              <p><strong>EVENT</strong> <code>onPeersReady</code></p>

            </div>
            
        </li>
        
        
        <li id="section-48">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-48">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>Peers.prototype.onPeersReady = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{


	setImmediate(<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nextBanManager</span> (<span class="hljs-params"></span>) </span>{
		__private.banManager(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
			<span class="hljs-keyword">if</span> (err) {
				library.logger.error(<span class="hljs-string">'Ban manager timer:'</span>, err);
			}
			setTimeout(nextBanManager, <span class="hljs-number">65</span> * <span class="hljs-number">1000</span>);
		});
	});
};</pre></div></div>
            
        </li>
        
        
        <li id="section-49">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-49">&#182;</a>
              </div>
              <p>Shared</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>
shared.getPeers = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req, cb</span>) </span>{
	library.schema.validate(req.body, schema.getPeers, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
		<span class="hljs-keyword">if</span> (err) {
			<span class="hljs-keyword">return</span> setImmediate(cb, err[<span class="hljs-number">0</span>].message);
		}

		<span class="hljs-keyword">if</span> (req.body.limit &lt; <span class="hljs-number">0</span> || req.body.limit &gt; <span class="hljs-number">100</span>) {
			<span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-string">'Invalid limit. Maximum is 100'</span>);
		}

		__private.getByFilter(req.body, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, peers</span>) </span>{
			<span class="hljs-keyword">if</span> (err) {
				<span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-string">'Failed to get peers'</span>);
			}

			<span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-literal">null</span>, {<span class="hljs-attr">peers</span>: peers});
		});
	});
};

shared.getPeer = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req, cb</span>) </span>{
	library.schema.validate(req.body, schema.getPeer, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
		<span class="hljs-keyword">if</span> (err) {
			<span class="hljs-keyword">return</span> setImmediate(cb, err[<span class="hljs-number">0</span>].message);
		}

		<span class="hljs-keyword">var</span> peer = __private.peers[req.body.ip+<span class="hljs-string">":"</span>+req.body.port];
		<span class="hljs-keyword">if</span> (peer) {
			<span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-literal">null</span>, {<span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">peer</span>: peer});
		} <span class="hljs-keyword">else</span> {
			<span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-literal">null</span>, {<span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>, <span class="hljs-attr">error</span>: <span class="hljs-string">'Peer not found'</span>});
		}</pre></div></div>
            
        </li>
        
        
        <li id="section-50">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-50">&#182;</a>
              </div>
              <p>__private.getByFilter({
    ip: req.body.ip,
    port: req.body.port
}, function (err, peers) {
    if (err) {
        return setImmediate(cb, ‘Failed to get peer’);
    }</p>
<pre><code><span class="hljs-keyword">if</span> (peers.length) {
    <span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-literal">null</span>, {<span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">peer</span>: peers[<span class="hljs-number">0</span>]});
} <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-literal">null</span>, {<span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>, <span class="hljs-attr">error</span>: <span class="hljs-string">'Peer not found'</span>});
}
</code></pre><p>});</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>	});
};

shared.version = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req, cb</span>) </span>{
	<span class="hljs-keyword">return</span> setImmediate(cb, <span class="hljs-literal">null</span>, {<span class="hljs-attr">version</span>: library.config.version, <span class="hljs-attr">build</span>: library.build});
};</pre></div></div>
            
        </li>
        
        
        <li id="section-51">
          
            <div class="annotation">
          
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-51">&#182;</a>
              </div>
              <p>Export</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">module</span>.exports = Peers;</pre></div></div>
            
        </li>
        
    </ul>
  </div>
</body>
</html>
